#ifndef _SOCKET_TCPSERVER_H_
#define _SOCKET_TCPSERVER_H_

#include <set>
using std::set;
#include <map>
using std::map;

#include "socket.h"
#include "thread.h"

typedef set<int>    SocketFdset;

typedef set<string> SocketAddrinfoset;

typedef map<string, SocketInfo*> SocketInfoMap;

class CTcpServer : public CSocket
{
    friend THREAD_HANDLE(tcpserver_send_thread, param);

    friend THREAD_HANDLE(tcpserver_recv_thread, param);

    friend THREAD_HANDLE(tcpserver_accept_thread, param);

public:

    CTcpServer();

    virtual ~CTcpServer();

    void RemoveSocketInfo(const char* addrinfo);

    void SetThreadCount(int sendcount, int recvcount);

    virtual bool OnSendMsg(SendBuffer* sendbuf);
    
    virtual void OnAccept(string addrinfo);

    virtual bool StartSocket(ushort port);

    virtual int OnRecvMsg(const char* addrinfo, const char* inbuf, int inlen) = 0;

private:

    void Clean();

    void AcceptThread();

    bool StartSendThread();

    bool StartRecvThread();

    void RecvThread(int index);

    void SendThread(int index);

    void EpollRecv(int index);

    void DealAddrinfoMap(int index);

    void RecvMsg(const char* addrinfo, SocketInfo* socketinfo);

protected:

    bool m_isrun;

    int  m_sendthreadcount;

    CThread** m_sendthreads;

    SendBufferQueue** m_sendqueues;

    int m_recvthreadcount;

    CMutex**  m_mutexs;

    SocketFdset** m_fdsets;

    CThread** m_recvthreads;
    
    SocketInfoMap** m_socketinfomaps;

    SocketAddrinfoset** m_addrinfoappends;

    SocketAddrinfoset** m_addrinforemoves;

    CThread m_acceptthread;
};

#endif //_SOCKET_TCPSERVER_H_
